﻿
#include "GActivityMonsAttackCity.h"
#include "ServerModule/LogicActivityModule.h"
#include "Character/CreatureMgr.h"
#include "Character/monster/MonsterRefCfg.h"
#include "Character/npc/Npc.h"
#include "PlaneMgr/PlaneMgr.h"
#include "Duplicate/DuplicateMgr.h"
#include "Character/drop/DropMgr.h"
#include "Common/TableData/MonsterMonsterCfg.h"
#include "PlaneMgr/PlaneMgr.h"
#include "Common/OperateLimitDefine.h"
#include "Character/HuoYueDuPart.h"
#include "Character/newAI/behaviac/CreatureCommonAI.h"

GActivityMonsAttackCity::GActivityMonsAttackCity()
{
	Clear();
}

GActivityMonsAttackCity::~GActivityMonsAttackCity()
{

}

void GActivityMonsAttackCity::Clear()
{
	m_averageLevel = 0;
	m_minLevel = 0;
	m_maxLevel = 0;
	m_totalLevDiff = 0;
	m_wavePerLevel = 0;
	m_curWave = 0;
	m_curLevel = 0;
	m_mapId = 0;
	m_cfg.Clear();
	m_mapAreaMonsData.clear();
	m_setPointMons.clear();
	m_setFightNpc.clear();
}

void GActivityMonsAttackCity::Init(uint32_t activityId)
{
	GActivity::Init(activityId);
}

void GActivityMonsAttackCity::UnInit()
{
	GActivity::UnInit();
	//取消订阅，取消定时器
	g_GetEvent()->UnSubscribeAll(this);
	g_GetTimerAxis()->KillAllTimer(this);
	//回收所有的场景怪
	RecycleAllMons();
	//显示场景所有战斗NPC
	DisplayFightNpc();
	//清空
	Clear();
}

void GActivityMonsAttackCity::OnActivityStart()
{
	//刷新水晶怪
	if (!FreshCrystalMons())
	{
		MMOLOG_FMT_ERROR("GActivityMonsAttackCity::OnActivityStart....FreshCrystalMons failed...");
		return;
	}
	//初始化攻击怪信息
	if (!InitAttackMons())
	{
		MMOLOG_FMT_ERROR("GActivityMonsAttackCity::OnActivityStart....InitAttackMons failed...");
		return;
	}
	//刷新据点怪
	FreshPointMons();
	//隐藏战斗NPC
	HideFightNpc();
	//
	MMOLOG_FMT_INFO("MonsAttackCity start...id:%u, averagelev:%d,ceilLev:%d, floorLev:%d, minlev:%d,maxlev:%d,m_wavePerLevel:%d,totalwave:%d ", GetId(), m_averageLevel, m_cfg.ceilLev, m_cfg.floorLev, m_minLevel, m_maxLevel, m_wavePerLevel, m_cfg.totalWave);
	//订阅怪物死亡事件
	SubScribleMonsEvent();
	//刷新攻击怪
	FreshAttackMons();
}



void GActivityMonsAttackCity::OnActivityStop()
{
	//取消订阅，取消定时器
	g_GetEvent()->UnSubscribeAll(this);
	g_GetTimerAxis()->KillAllTimer(this);
	if (m_setCrystalMons.size() > 0) 
	{
		/*
		跑马灯公告：“怪物攻城活动已经结束，我们的勇士成功守护能量水晶，誓约城出现了大量福利宝箱，大家快去抢福利吧。
		*/
		//通知结果
		NotifyMonsAttackCityResult(RET_SUCCESS);
		//刷新宝箱怪
		FreshBoxMons();
		//完成活动
		FinishActivity();
	}
	//回收所有的场景怪
	RecycleAllMons();
	//显示战斗NPC
	DisplayFightNpc();
	//清空
	Clear();
}

bool GActivityMonsAttackCity::InitMonsAttackCity(const MonsAttackCityProto &proto)
{
	//先清空数据
	Clear();
	//
	m_averageLevel = proto.average_level();
	m_mapId = proto.mapid();
	m_averageLevel = (m_averageLevel < 1) ? 1 : m_averageLevel;
	if (nullptr == g_GetSceneMgr()->GetScene(m_mapId))
	{
		MMOLOG_FMT_ERROR("InitMonsAttackCity....can not find scene....mapid:%u ",m_mapId);
		return false;
	}
	//
	if (!g_GetGActivityMgr()->LuaGetMonsAttackCity(m_cfg))
	{
		MMOLOG_FMT_ERROR("InitMonsAttackCity....LuaGetMonsAttackCity failed...");

		//失败了，直接清空数据
		Clear();
		return false;
	}
	//等级下限
	m_minLevel = m_averageLevel - m_cfg.floorLev;
	//等级上限
	m_maxLevel = m_averageLevel + m_cfg.ceilLev;
	//总的等级差
	m_totalLevDiff = m_maxLevel - m_minLevel;
	m_totalLevDiff = (m_totalLevDiff < 1) ? 1 : m_totalLevDiff;
	//每个等级多少波怪
	m_wavePerLevel = m_cfg.totalWave / m_totalLevDiff;
	m_wavePerLevel = m_wavePerLevel < 1 ? 1 : m_wavePerLevel;
	//当前波数
	m_curWave = 1;
	//当前刷新等级
	m_curLevel = m_minLevel;


	return true;
}


void  GActivityMonsAttackCity::OnTimer(uint32_t nTimerID)
{
	switch (nTimerID)
	{
	case ETimer_ID_Next:
		{
			FreshAttackMons();
		}
		break;
	case ECrystall_AllDie:
		{
			OnCrystalAllDie();
			break;
		}
	case ETimer_ID_BigBoss:
		{
			FreshBigBossMons();
		}
		break;
	default:
		break;
	}
}

void GActivityMonsAttackCity::OnExecute(uint16_t nEventID, uint64_t nSrcID, uint8_t bySrcType, void *pContext, int32_t nLen)
{
	switch (nEventID)
	{
	case EVENT_CREATURE_DEAD:
		{
			DieEvent *pDieEvent = (DieEvent*)pContext;
			OnMonsDie(pDieEvent);
		}
		break;
	}
}

bool GActivityMonsAttackCity::IsCrystalMons(CharIDType cid)	//是否是水晶怪
{
	SET_UINT64::iterator iter = m_setCrystalMons.find(cid);
	return (iter != m_setCrystalMons.end()) ? true : false;
}

bool GActivityMonsAttackCity::IsAttackMons(CharIDType cid)//是否是攻城怪
{
	SET_UINT64::iterator iter = m_setAttackMons.find(cid);
	return (iter != m_setAttackMons.end()) ? true : false;
}

Monster *GActivityMonsAttackCity::GetAttackMonster(CharIDType cid)//获取攻城怪
{
	if (IsAttackMons(cid))
	{
		return g_GetSceneMgr()->GetMonster(m_mapId, cid);
	}
	return nullptr;
}

Monster *GActivityMonsAttackCity::GetCryStalMonster(CharIDType cid)	//获取水晶怪
{
	if (IsCrystalMons(cid))
	{
		return g_GetSceneMgr()->GetMonster(m_mapId, cid);
	}
	return nullptr;
}

void GActivityMonsAttackCity::SubScribleMonsEvent()//订阅怪物事件
{
	//订阅boss被攻击事件
	if (!g_GetEvent()->Subscribe(this, EVENT_CREATURE_DEAD, 0, CREATURE_MONSTER, "GActivityMonsAttackCity"))
	{
		MMOLOG_FMT_ERROR("[logic] GActivityMonsAttackCity::SubScribleMonsEvent... subcribe mons die failed.... mapid:%u ", m_mapId);
	}
}

bool GActivityMonsAttackCity::FreshCrystalMons()
{
	bool flag = false;
	VecAttackMonsSingle::iterator iter = m_cfg.vecCrystal.begin();
	for (; iter != m_cfg.vecCrystal.end(); ++iter)
	{
		AttackMonsSingleCfgInfo &info = (*iter);
		Point3<float> pos = g_GetMapLocationCfg()->RandPosInArea(info.areaId);
		MonsterExtendInfo extrend;
		extrend.set_level(m_averageLevel);
		Point3<float> dir = Point3<float>(0, 0, 1);
		MonsCreateParam createParam;
		createParam.createType = EMonsCreateType_Activity;
		createParam.createTypeVal = GetId();
		Monster *pMonster = g_GetCreatureMgr()->CreateMonster(info.monsId, m_mapId, pos, createParam,dir, -1, &extrend);
		if (nullptr != pMonster)
		{
			flag = true;
			CharIDType cid = pMonster->GetCid();
			//
			m_setCrystalMons.insert(cid);
			//
			MMOLOG_FMT_INFO("[logic] GActivityMonsAttackCity::FreshCrystalMons.....areaid:%u  mapid:%u ,monsid:%u,mons_cid:%lu,pos:%f,%f,%f,m_averageLevel:%d  ", info.areaId, m_mapId, info.monsId, cid, pos.x, pos.y, pos.z, m_averageLevel);
		}
		else
		{
			LogErrFmtPrint("[logic] GActivityMonsAttackCity::FreshCrystalMons.....areaid:%u  mapid:%u ,monsid:%u ,pos:%f,%f,%f,m_averageLevel:%d ", info.areaId, m_mapId, info.monsId, pos.x, pos.y, pos.z, m_averageLevel);
		}
	}
	return flag;
}

void GActivityMonsAttackCity::FreshBoxMons()//刷新宝箱怪
{
	int32_t isize = m_setCrystalMons.size();
	AttackMonsSingleMap::iterator iterNum = m_cfg.mapBoxMons.find(isize);
	if (iterNum == m_cfg.mapBoxMons.end())
	{
		LogErrFmtPrint("GActivityMonsAttackCity::FreshBoxMons....iterNum == m_cfg.mapBoxMons.end()...isize:%d ", isize);
		return;
	}
	MMOLOG_FMT_INFO("GActivityMonsAttackCity::FreshBoxMons....leftNum:%d... ", isize);
	VecAttackMonsSingle &vecAttackMons = iterNum->second;
	VecAttackMonsSingle::iterator iter = vecAttackMons.begin();
	for (; iter != vecAttackMons.end(); ++iter)
	{
		AttackMonsSingleCfgInfo &info = (*iter);
		for (int32_t i = 0; i < info.monsNum; ++i)
		{
			Point3<float> pos = g_GetMapLocationCfg()->RandPosInArea(info.areaId);
			MonsCreateParam createParam;
			createParam.createType = EMonsCreateType_Activity;
			createParam.createTypeVal = GetId();
			Monster *pMonster = g_GetCreatureMgr()->CreateMonster(info.monsId, m_mapId, pos, createParam);
			if (nullptr != pMonster)
			{
				CharIDType cid = pMonster->GetCid();
				MMOLOG_FMT_INFO("[logic] GActivityMonsAttackCity::FreshCrystalMons.....areaid:%u  mapid:%u ,monsid:%u,mons_cid:%lu,i:%d, pos:%f,%f,%f ", info.areaId, m_mapId, info.monsId, cid, i, pos.x, pos.y, pos.z);
			}
			else
			{
				LogErrFmtPrint("[logic] GActivityMonsAttackCity::FreshCrystalMons.....areaid:%u  mapid:%u ,monsid:%u,i:%d,pos:%f,%f,%f ", info.areaId, m_mapId, info.monsId, i, pos.x, pos.y, pos.z);
			}
		}		
	}
}

void GActivityMonsAttackCity::FreshPointMons() //刷新据点怪
{
	VecPointMonsCfg::iterator iter = m_cfg.vecPointMons.begin();
	for (; iter != m_cfg.vecPointMons.end(); ++iter)
	{
		PointMonsCfgInfo &info = (*iter);
		Point3<float> pos(info.fx,info.fy,info.fz);
		MonsCreateParam createParam;
		createParam.createType = EMonsCreateType_Activity;
		createParam.createTypeVal = GetId();
		Monster *pMonster = g_GetCreatureMgr()->CreateMonster(info.monsId, m_mapId, pos, createParam);
		if (nullptr != pMonster)
		{
			CharIDType cid = pMonster->GetCid();
			//
			m_setPointMons.insert(cid);
			//
			MMOLOG_FMT_INFO("[logic] GActivityMonsAttackCity::FreshPointMons..... mapid:%u ,monsid:%u,mons_cid:%lu,pos:%f,%f,%f  ", m_mapId, info.monsId, cid, pos.x, pos.y, pos.z);
		}
		else
		{
			LogErrFmtPrint("[logic] GActivityMonsAttackCity::FreshPointMons.....mapid:%u ,monsid:%u ,pos:%f,%f,%f",  m_mapId, info.monsId, pos.x, pos.y, pos.z);
		}
	}
}

bool GActivityMonsAttackCity::InitAttackMons()//初始化
{
	if (m_cfg.mapAttackMons.size() <= 0)
	{
		MMOLOG_FMT_ERROR("GActivityMonsAttackCity::InitAttackMons....m_cfg.mapAttackMons.size() <= 0....");
		return false;
	}
	AttackMonsCfgMap::iterator iter = m_cfg.mapAttackMons.begin();
	for (; iter != m_cfg.mapAttackMons.end(); ++iter)
	{
		if (m_curLevel <= iter->first)
		{
			m_curAttackCfg.clear();
			m_curAttackCfg = iter->second;
			return true;
		}
	}

	return false;
}

void GActivityMonsAttackCity::FreshAttackMons()//刷新攻击怪
{
	bool bossfinish = false;
	int32_t millsec = 0;
	if (!m_curAttackCfg.brushFinishMons()) //攻击怪没有刷完
	{
		//总数量减少
		int32_t relnum = m_curAttackCfg.perMonsNum;
		if (m_curAttackCfg.totalMonsNum < relnum)
		{
			relnum = m_curAttackCfg.totalMonsNum;
		}
		m_curAttackCfg.totalMonsNum -= relnum;
		MAP_UINT32_UINT32::iterator iterArea = m_cfg.mapAreaLine.begin();
		for (; iterArea != m_cfg.mapAreaLine.end(); ++iterArea)
		{
			for (int32_t i = 0; i < relnum; i++)
			{
				FreshSingleMonsAndBoss(EFreshType_Mons,i, iterArea->first, iterArea->second);
			}
		}

		millsec = m_curAttackCfg.perMonsSec * 1000;
		if (m_curAttackCfg.brushFinishMons())
		{
			if (!m_curAttackCfg.brushFinishBoss())
			{
				millsec = m_curAttackCfg.perBossSec * 1000;
			}
			else
			{
				bossfinish = true;
			}
		}
	}
	else if (!m_curAttackCfg.brushFinishBoss()) //boss还没刷完
	{
		//总数量减少
		int32_t relnum = m_curAttackCfg.perBossNum;
		if (m_curAttackCfg.totalBossNum < relnum)
		{
			relnum = m_curAttackCfg.totalBossNum;
		}
		m_curAttackCfg.totalBossNum -= relnum;
		MAP_UINT32_UINT32::iterator iterArea = m_cfg.mapAreaLine.begin();
		for (; iterArea != m_cfg.mapAreaLine.end(); ++iterArea)
		{
			for (int32_t i = 0; i < relnum; i++)
			{
				FreshSingleMonsAndBoss(EFreshType_Boss,i, iterArea->first, iterArea->second);
			}
		}
		//
		if (m_curAttackCfg.brushFinishBoss())
		{
			bossfinish = true;
		}
		else
		{
			millsec = m_curAttackCfg.perBossSec * 1000;
		}
	}
	else
	{
		bossfinish = true;
	}

	if (bossfinish) //当前波的boss刷新完了
	{
		//如果达到最高等级，则刷完了所有怪
		if (m_curLevel >= m_maxLevel)
		{
			MMOLOG_FMT_INFO("GActivityMonsAttackCity::FreshAttackMons...all monster has fresh finished....m_curLevel:%d,minlevel:%d,maxlev:%d,m_curWave:%d ", m_curLevel, m_minLevel, m_maxLevel, m_curWave);
			return;
		}
		//
		if (m_curWave >= m_wavePerLevel)
		{
			//当前等级的怪物波数刷完了
			MMOLOG_FMT_INFO("GActivityMonsAttackCity::FreshAttackMons...level wave monster has fresh finished....m_curLevel:%d,minlevel:%d,maxlev:%d,m_wave:%d ", m_curLevel, m_minLevel, m_maxLevel, m_curWave);
			//
			if (m_curAttackCfg.brushFinshBigBoss())
			{
				//当前等级的怪物波数刷完了,并且 大boss也刷完了 需要刷新下一个等级的怪,当前刷怪等级+1
				m_curLevel += 1;
				//波数为1
				m_curWave = 1;
				//重新初始化当前等级的刷怪信息
				if (!InitAttackMons())
				{
					MMOLOG_FMT_ERROR("GActivityMonsAttackCity::FreshAttackMons...InitAttackMons failed....m_curLevel:%d,minlevel:%d,maxlev:%d,m_curWave:%d ", m_curLevel, m_minLevel, m_maxLevel, m_curWave);
					return;
				}
			}
			else
			{
				//开始开启定时器刷新大boss
				MMOLOG_FMT_INFO("GActivityMonsAttackCity::FreshAttackMons...start fresh big boss timer....m_curLevel:%d,minlevel:%d,maxlev:%d,m_wave:%d ", m_curLevel, m_minLevel, m_maxLevel, m_curWave);
				millsec = m_curAttackCfg.perBigBossSec * 1000;
				millsec = (millsec <= 0) ? 500 : millsec;
				g_GetTimerAxis()->KillTimer(ETimer_ID_BigBoss, this);
				if (!g_GetTimerAxis()->SetTimer(ETimer_ID_BigBoss, millsec, this, 1))
				{
					MMOLOG_FMT_ERROR("GActivityMonsAttackCity::FreshAttackMons...ETimer_ID_BigBoss SetTimer failed....m_curLevel:%d,minlevel:%d,maxlev:%d,m_curWave:%d,millsec:%d ", m_curLevel, m_minLevel, m_maxLevel, m_curWave, millsec);
				}
				return;
			}			
		}
		else
		{
			//当前等级波数增加
			m_curWave += 1;
			//重新初始化当前等级 下一波刷怪的信息
			if (!InitAttackMons())
			{
				MMOLOG_FMT_ERROR("GActivityMonsAttackCity::FreshAttackMons 11...InitAttackMons failed....m_curLevel:%d,minlevel:%d,maxlev:%d,m_curWave:%d ", m_curLevel, m_minLevel, m_maxLevel, m_curWave);
				return;
			}
		}

		//下一次刷新是一大波刷新时间
		millsec = m_cfg.waveSec * 1000;
	}
	

	millsec = (millsec <= 0) ? 500 : millsec;
	g_GetTimerAxis()->KillTimer(ETimer_ID_Next, this);
	if (!g_GetTimerAxis()->SetTimer(ETimer_ID_Next, millsec, this, 1))
	{
		MMOLOG_FMT_ERROR("GActivityMonsAttackCity::FreshAttackMons...SetTimer failed....m_curLevel:%d,minlevel:%d,maxlev:%d,m_curWave:%d ", m_curLevel, m_minLevel, m_maxLevel, m_curWave);
	}
}

void GActivityMonsAttackCity::FreshBigBossMons()//刷新大BOSS怪
{
	uint32_t monsId = m_curAttackCfg.bigBossId;
	m_curAttackCfg.totalBigBossNum -= 1;//默认是一个
	MAP_UINT32_UINT32::iterator iterArea = m_cfg.mapAreaLine.begin();
	for (; iterArea != m_cfg.mapAreaLine.end(); ++iterArea)
	{
		uint32_t areaId = iterArea->first;
		uint32_t lineId = iterArea->second;		
		Point3<float> pos = g_GetMapLocationCfg()->RandPosInArea(areaId);
		MonsCreateParam createParam;
		createParam.createType = EMonsCreateType_Activity;
		createParam.createTypeVal = GetId();
		Monster *pMonster = g_GetCreatureMgr()->CreateMonster(monsId, m_mapId, pos, createParam);
		if (nullptr != pMonster)
		{
			CharIDType cid = pMonster->GetCid();
			m_setAttackMons.insert(cid);
			if (lineId > 0)
			{
				const PathRefLocation *pPathLoc = g_GetMapLocationCfg()->GetPathRefLoc(lineId);
				if (nullptr != pPathLoc)
				{
					pMonster->SetAiPath(lineId, ENUM_MONSTER_PATROL_TYPE_ONE_WAY_TRIP);
				}
				else
				{
					LogErrFmtPrint("GActivityMonsAttackCity:FreshBigBossMons...nullptr == pPathLoc...  mapid:%u ,curlev:%d,areaid:%u, lineid:%d , monsid:%u, cid:%lu, pos:[%f,%f,%f],m_curWave:%d ..", m_mapId, m_curLevel, areaId, lineId, monsId, cid, pos.x, pos.y, pos.z, m_curWave);
				}
			}
			MMOLOG_FMT_INFO("GActivityMonsAttackCity:FreshBigBossMons...mapid:%u ,curlev:%d, areaid:%u, lineid:%d,  monsid:%u, cid:%lu, pos:[%f,%f,%f] ,m_curWave:%d..", m_mapId, m_curLevel, areaId, lineId, monsId, cid, pos.x, pos.y, pos.z, m_curWave);
		}
		else
		{
			LogErrFmtPrint("GActivityMonsAttackCity:FreshBigBossMons...CreateMonster failed.....mapid:%u, curlev:%d,areaid:%u, lineid:%d, monsid:%u, pos:[%f,%f,%f],m_curWave:%d ..", m_mapId, m_curLevel, areaId, lineId, monsId, pos.x, pos.y, pos.z, m_curWave);
		}
	}

	//大boss只有一波，一次刷完,刷完之后进入下一波小怪刷新
	FreshAttackMons();
}

uint32_t GActivityMonsAttackCity::RandAttackMonsAndBoss(int8_t freshType)//随机攻击怪和boss
{
	SET_UINT32 *pSet = nullptr;
	if (EFreshType_Mons == freshType)
	{
		pSet = &m_curAttackCfg.setMons;
	}
	else
	{
		pSet = &m_curAttackCfg.setBoss;
	}
	if (nullptr == pSet)
	{
		MMOLOG_FMT_ERROR("GActivityMonsAttackCity::RandAttackMonsAndBoss....nullptr == pSet... freshtype:%d ", freshType);
		return 0;
	}
	int32_t isize = pSet->size();
	int32_t idx = Random(1, isize);
	uint32_t monsId = 0;
	SET_UINT32::iterator iter = pSet->begin();
	for (; iter != pSet->end(); ++iter)
	{
		--idx;
		if (idx <= 0)
		{
			monsId = (*iter);
			break;
		}
	}
	return monsId;
}

void GActivityMonsAttackCity::FreshSingleMonsAndBoss(int8_t freshType,int32_t idx, uint32_t areaId, uint32_t lineId) //刷新单个怪或者boss
{
	uint32_t monsId = RandAttackMonsAndBoss(freshType);
	if (monsId <= 0)
	{
		MMOLOG_FMT_ERROR("GActivityMonsAttackCity::FreshSingleMonsAndBoss....monsId <= 0...areaid:%u, lineId:%u, freshtype:%d, curlev:%d, idx:%d，m_curWave：%d ", areaId, lineId, freshType, m_curLevel, idx, m_curWave);
		return;
	}
	Point3<float> pos = g_GetMapLocationCfg()->RandPosInArea(areaId);
	MonsCreateParam createParam;
	createParam.createType = EMonsCreateType_Activity;
	createParam.createTypeVal = GetId();
	Monster *pMonster = g_GetCreatureMgr()->CreateMonster(monsId, m_mapId, pos, createParam);
	if (nullptr != pMonster)
	{
		CharIDType cid = pMonster->GetCid();
		m_setAttackMons.insert(cid);
		if (lineId > 0)
		{
			const PathRefLocation *pPathLoc = g_GetMapLocationCfg()->GetPathRefLoc(lineId);
			if (nullptr != pPathLoc)
			{
				pMonster->SetAiPath(lineId, ENUM_MONSTER_PATROL_TYPE_ONE_WAY_TRIP);
			}
			else
			{
				LogErrFmtPrint("GActivityMonsAttackCity:FreshSingleMonsAndBoss...nullptr == pPathLoc...  mapid:%u ,freshType:%d,curlev:%d, idx:%d,areaid:%u, lineid:%d , monsid:%u, cid:%lu, pos:[%f,%f,%f],m_curWave:%d ..", m_mapId, freshType, m_curLevel, idx, areaId, lineId, monsId, cid, pos.x, pos.y, pos.z, m_curWave);
			}
		}
		MMOLOG_FMT_INFO("GActivityMonsAttackCity:FreshSingleMonsAndBoss...mapid:%u ,freshType:%d,curlev:%d, idx:%d, areaid:%u, lineid:%d,  monsid:%u, cid:%lu, pos:[%f,%f,%f] ,m_curWave:%d..", m_mapId, freshType, m_curLevel, idx, areaId, lineId, monsId, cid, pos.x, pos.y, pos.z, m_curWave);
	}
	else
	{
		LogErrFmtPrint("GActivityMonsAttackCity:FreshSingleMonsAndBoss...CreateMonster failed.....mapid:%u,freshType:%d, curlev:%d, idx:%d,areaid:%u, lineid:%d, monsid:%u, pos:[%f,%f,%f],m_curWave:%d ..", m_mapId, freshType, m_curLevel, idx, areaId, lineId, monsId, pos.x, pos.y, pos.z, m_curWave);
	}

}

void GActivityMonsAttackCity::OnMonsDie(DieEvent *pDieEvent)//怪物死亡
{
	if (nullptr == pDieEvent)
	{
		return;
	}
	if (pDieEvent->sceneId != m_mapId)
	{
		return;
	}
	bool attendFlag = false;
	if (IsCrystalMons(pDieEvent->nCid))
	{
		attendFlag = true;
		m_setCrystalMons.erase(pDieEvent->nCid);
		if (m_setCrystalMons.size() <= 0) 
		{
			//水晶怪全部死亡了
			LogInfoFmtPrint(" GActivityMonsAttackCity::OnMonsDie...all crystal monster die...");
			g_GetTimerAxis()->KillTimer(ECrystall_AllDie, this);
			g_GetTimerAxis()->SetTimer(ECrystall_AllDie, 500, this, 1);
		}
	}
	else if (IsAttackMons(pDieEvent->nCid))
	{
		attendFlag = true;
		m_setAttackMons.erase(pDieEvent->nCid);
	}

	//参加标记
	if (attendFlag)
	{
		m_joinList.insert(pDieEvent->killerCid);
		Participating(pDieEvent->killerCid);
	}
}

void GActivityMonsAttackCity::OnCrystalAllDie()//水晶怪全部死亡
{
	/*
	1.活动时间内，四个能量水晶都被击碎，关闭所有怪物刷新，活动直接结束
	2.活动结束后誓约所有怪物全部消失。
	3.城地图跑马灯公告：“怪物攻城活动已经结束，很遗憾我们没能抵御怪物的攻击，希望勇士们再接再厉，在下一次活动中获得更多的收获。”
	*/
	MMOLOG_FMT_INFO("GActivityMonsAttackCity::OnCrystalAllDie....");
	//通知结果
	NotifyMonsAttackCityResult(RET_FAIL);
	//
	g_GetTimerAxis()->KillAllTimer(this);
	g_GetEvent()->UnSubscribeAll(this);
	RecycleAllMons();
	//显示战斗NPC
	DisplayFightNpc();
}

void GActivityMonsAttackCity::RecycleAllMons() //回收所有的怪
{
	Scene *pScene = g_GetSceneMgr()->GetScene(m_mapId);
	if (nullptr == pScene)
	{
		//MMOLOG_FMT_ERROR("GActivityMonsAttackCity::RecycleAllMons...nullptr == pScene ... mapid:%u ", m_mapId);
		return;
	}
	SET_UINT64::iterator iterMons = m_setAttackMons.begin();
	for (; iterMons != m_setAttackMons.end(); ++iterMons)
	{
		CharIDType cid = (*iterMons);
		Monster *pMonster = pScene->GetMonster(cid);
		if (nullptr != pMonster)
		{
			if (pMonster->LeaveScene())
			{
				g_GetCreatureMgr()->WaitDestory(cid);
			}
			else
			{
				MMOLOG_FMT_ERROR("GActivityMonsAttackCity::RecycleAllMons...attack pMonster->LeaveScene() failed.. mapid:%u,cid:%lu ", m_mapId, cid);
			}
		}
	}
	m_setAttackMons.clear();

	SET_UINT64::iterator iterCrystal = m_setCrystalMons.begin();
	for (; iterCrystal != m_setCrystalMons.end(); ++iterCrystal)
	{
		CharIDType cid = (*iterCrystal);
		Monster *pMonster = pScene->GetMonster(cid);
		if (nullptr != pMonster)
		{
			if (pMonster->LeaveScene())
			{
				g_GetCreatureMgr()->WaitDestory(cid);
			}
			else
			{
				MMOLOG_FMT_ERROR("GActivityMonsAttackCity::RecycleAllMons...crystal pMonster->LeaveScene() failed.. mapid:%u,cid:%lu ", m_mapId, cid);
			}
		}
	}
	m_setCrystalMons.clear();

	SET_UINT64::iterator iterPoint = m_setPointMons.begin();
	for (; iterPoint != m_setPointMons.end(); ++iterPoint)
	{
		CharIDType cid = (*iterPoint);
		Monster *pMonster = pScene->GetMonster(cid);
		if (nullptr != pMonster)
		{
			if (pMonster->LeaveScene())
			{
				g_GetCreatureMgr()->WaitDestory(cid);
			}
			else
			{
				MMOLOG_FMT_ERROR("GActivityMonsAttackCity::RecycleAllMons...point pMonster->LeaveScene() failed.. mapid:%u,cid:%lu ", m_mapId,cid);
			}
		}
	}
	m_setPointMons.clear();
}

void GActivityMonsAttackCity::HideFightNpc()	//隐藏战斗NPC
{
	Scene *pScene = g_GetSceneMgr()->GetScene(m_mapId);
	if (nullptr == pScene)
	{
		MMOLOG_FMT_INFO("GActivityMonsAttackCity::HideFightNpc...nullptr == pScene ... mapid:%u ", m_mapId);
		return;
	}
	SET_UINT64 setAllFightNpc;
	setAllFightNpc.clear();
	pScene->GetAllFightNpc(setAllFightNpc);

	SET_UINT64::iterator iterNpc = setAllFightNpc.begin();
	for (; iterNpc != setAllFightNpc.end(); ++iterNpc)
	{
		CharIDType cid = (*iterNpc);
		Npc *pNpc = pScene->GetNpc(cid);
		if (nullptr != pNpc)
		{
			CreatureCommonAI *pAi = pNpc->GetAiData();
			if (nullptr != pAi)
			{
				pAi->SetAiEnable(false);

			}
			pNpc->SetCanBeSeenFlag(false);
			MMOLOG_FMT_INFO("GActivityMonsAttackCity::HideFightNpc..mapid:%u, id:%lu, npcid:%u ",m_mapId,cid,pNpc->GetConfigId())
		}
	}

}


void GActivityMonsAttackCity::DisplayFightNpc()	//显示战斗NPC
{
	Scene *pScene = g_GetSceneMgr()->GetScene(m_mapId);
	if (nullptr == pScene)
	{
		//MMOLOG_FMT_INFO("GActivityMonsAttackCity::DisplayFightNpc...nullptr == pScene ... mapid:%u ", m_mapId);
		return;
	}
	SET_UINT64 setAllFightNpc;
	setAllFightNpc.clear();
	pScene->GetAllFightNpc(setAllFightNpc);

	SET_UINT64::iterator iterNpc = setAllFightNpc.begin();
	for (; iterNpc != setAllFightNpc.end(); ++iterNpc)
	{
		CharIDType cid = (*iterNpc);
		Npc *pNpc = pScene->GetNpc(cid);
		if (nullptr != pNpc)
		{
			CreatureCommonAI *pAi = pNpc->GetAiData();
			if (nullptr != pAi)
			{
				pAi->SetAiEnable(true);

			}
			pNpc->SetCanBeSeenFlag(true);
			MMOLOG_FMT_INFO("GActivityMonsAttackCity::DisplayFightNpc..mapid:%u, id:%lu, npcid:%u ", m_mapId, cid, pNpc->GetConfigId())
		}
	}
}

void GActivityMonsAttackCity::NotifyMonsAttackCityResult(int32_t result)//通知怪物攻城结果
{
	LCMonsAttackCityResult notify;
	notify.set_result(result);
	if (!g_GetLogicService()->SendDataToCenter(EMODULE_ID_ACTIVITY, LOGIC_TO_CENTER_MONS_ATTACK_CITY_RESULT, &notify))
	{
		MMOLOG_FMT_INFO("NotifyMonsAttackCityResult....SendDataToCenter failed...result:%d ",result);
	}
}